﻿namespace TestTool.Tests.Engine
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Sockets;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using TestTool.HttpTransport;
    using TestTool.HttpTransport.Interfaces;
    using TestTool.HttpTransport.Interfaces.Exceptions;
    using TestTool.Proxies.Onvif;
    using TestTool.Tests.Common.CommonUtils;
    using TestTool.Tests.Common.TestBase;
    using TestTool.Tests.Definitions.Data;
    using TestTool.Tests.Definitions.Enums;
    using TestTool.Tests.Definitions.Exceptions;
    using TestTool.Tests.Definitions.Features;
    using TestTool.Tests.Engine.Base.Definitions;
    using TestTool.Tests.Engine.Base.TestBase;

    public class FeaturesDefinitionProcess : BaseServiceTest<Device, DeviceClient>
    {
        private static TestInfo _descriptor;
        private List<Feature> _features;
        private FeaturesSet _featuresSet;
        private ImagingPortClient _imagingClient;
        private string _imagingServiceAddress;
        private bool _imagingSupported;
        private DeviceIOPortClient _ioClient;
        private string _ioServiceAddress;
        private bool _ioSupported;
        private TestTool.Proxies.Onvif.MediaClient _mediaClient;
        private string _mediaServiceAddress;
        private bool _mediaSupported;
        private PTZClient _ptzClient;
        protected string _ptzNode;
        private string _ptzServiceAddress;
        private bool _ptzSupported;
        private ReceiverPortClient _receiverClient;
        private string _receiverServiceAddress;
        private bool _receiverSupported;
        private RecordingPortClient _recordingControlClient;
        private string _recordingControlServiceAddress;
        private bool _recordingControlSupported;
        protected string _recordingToken;
        private ReplayPortClient _replayClient;
        private string _replayServiceAddress;
        private bool _replaySupported;
        private SearchPortClient _searchClient;
        private string _searchServiceAddress;
        private bool _searchSupported;
        protected string _secureOperation;
        private bool _warning;

        public event Action<DeviceInformation> DeviceInformationReceived;

        public event Action<Feature, bool> FeatureDefined;

        public event Action<Feature> FeatureDefinitionFailed;

        public event Action<string> ScopeDefined;

        public FeaturesDefinitionProcess(TestLaunchParam param) : base(param)
        {
            this._secureOperation = param.SecureMethod;
            this._ptzNode = param.PTZNodeToken;
            this._recordingToken = param.RecordingToken;
            this._featuresSet = FeaturesSet.CreateFeaturesSet();
        }

        protected void AddPtzConfiguration(string profileToken, string configurationToken)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            base.RunStep(() => client.AddPTZConfiguration(profileToken, configurationToken), "Add PTZ configuration");
            base.DoRequestDelay();
        }

        protected void AddVideoEncoderConfiguration(string profileToken, string configurationToken)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            base.RunStep(() => client.AddVideoEncoderConfiguration(profileToken, configurationToken), "Add Video Encoder configuration");
            base.DoRequestDelay();
        }

        protected void AddVideoSourceConfiguration(string profileToken, string configurationToken)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            base.RunStep(() => client.AddVideoSourceConfiguration(profileToken, configurationToken), "Add Video Source configuration");
            base.DoRequestDelay();
        }

        private void CheckDigestSupport()
        {
            Action action = null;
            base.LogTestEvent("Check Digest authentication support by sending request");
            base.LogTestEvent(string.Empty);
            bool supported = false;
            base.BeginStep("Check which method is to be used to define Digest/WS-Username support");
            MethodInfo mi = base.Client.GetType().GetMethod(this._secureOperation);
            base.LogStepEvent(string.Format("Use {0}", this._secureOperation));
            object[] parameters = null;
            if (this._secureOperation == "GetDeviceInformation")
            {
                parameters = new string[4];
            }
            else if (this._secureOperation == "GetCapabilities")
            {
                object[] objArray = new object[1];
                CapabilityCategory[] categoryArray = new CapabilityCategory[1];
                objArray[0] = categoryArray;
                parameters = objArray;
            }
            base.StepPassed();
            bool flag2 = false;
            Security wS = base._credentialsProvider.Security;
            if (wS == Security.None)
            {
                wS = Security.WS;
            }
            base._credentialsProvider.Security = Security.None;
            try
            {
                if (action == null)
                {
                    action = () => mi.Invoke(this.Client, parameters);
                }
                base.RunStep(action, string.Format("Invoke {0} without credentials supplied", this._secureOperation));
            }
            catch (Exception exception)
            {
                flag2 = true;
                Exception innerException = exception.InnerException;
                bool flag3 = false;
                if (innerException != null)
                {
                    if (innerException is AccessDeniedException)
                    {
                        supported = true;
                        flag3 = true;
                        base._credentialsProvider.Security = Security.Digest;
                        base.LogStepEvent("The DUT requires Digest authentication");
                        base.StepPassed();
                    }
                    else if (innerException is FaultException)
                    {
                        FaultException exc = innerException as FaultException;
                        base.LogFault(exc);
                        flag3 = true;
                        if (exc.IsValidOnvifFault("Sender/NotAuthorized") || exc.IsValidOnvifFault("Sender/NotAuthorized/SenderNotAuthorized"))
                        {
                            base.LogStepEvent("The DUT requires WS-Username token authentication");
                            base._credentialsProvider.Security = Security.WS;
                        }
                        else
                        {
                            this._warning = true;
                            base._credentialsProvider.Security = wS;
                            base.LogTestEvent("Warning: no security-related error occurred when sending request without credentials supplied.");
                        }
                        base.StepPassed();
                    }
                }
                if (!flag3)
                {
                    this.HandleException(exception.InnerException ?? exception);
                    base._credentialsProvider.Security = wS;
                    base.LogTestEvent("Warning: unexpected error occurred during checking Digest support" + Environment.NewLine);
                }
            }
            finally
            {
                base.DoRequestDelay();
            }
            if (!flag2)
            {
                this._warning = true;
                base.LogTestEvent("Warning: no error occurred when sending request without credentials supplied. Unable to check Digest support." + Environment.NewLine);
                base._credentialsProvider.Security = wS;
            }
            this.LogAndNotify(Feature.Digest, "Digest authentication", supported);
            base.LogTestEvent(string.Empty);
        }

        private void CheckNTPSupport()
        {
            base.LogTestEvent("Check NTP support by requesting NTP information");
            base.LogTestEvent(string.Empty);
            try
            {
                this.GetNTP();
                this.LogAndNotify(Feature.NTP, "NTP", true);
            }
            catch (FaultException)
            {
                base.StepPassed();
                this.LogAndNotify(Feature.NTP, "NTP", false);
                base.LogTestEvent(string.Empty);
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
                base.LogTestEvent("Warning: an error occurred during checking NTP functionality" + Environment.NewLine);
                this.LogAssumeSupported("NTP");
                this.ReportUndefined(Feature.NTP);
            }
        }

        protected bool CheckPTZSpaces<T>(T[] spaces)
        {
            bool flag = false;
            if (spaces != null)
            {
                flag = spaces.Length > 0;
            }
            return flag;
        }

        private void CloseClients()
        {
            foreach (ICommunicationObject obj2 in new ICommunicationObject[] { this._mediaClient, this._ptzClient, this._ioClient, this._imagingClient, this._replayClient })
            {
                if (obj2 != null)
                {
                    obj2.Close();
                }
            }
        }

        protected override DeviceClient CreateClient()
        {
            return new DeviceClient((HttpBinding) base.CreateBinding(true), new EndpointAddress(base._cameraAddress));
        }

        protected Profile CreateProfile(string name, string token)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            Profile profile = null;
            base.RunStep(delegate {
                profile = client.CreateProfile(name, token);
            }, "Create profile");
            base.DoRequestDelay();
            return profile;
        }

        private void DefineAnalyticsFeatures(Capabilities capabilities, Service[] services)
        {
            base.BeginStep("Define Analytics features");
            bool supported = false;
            if (services != null)
            {
                this.LogUsage("Use GetServices response");
                supported = services.FindService("http://www.onvif.org/ver20/analytics/wsdl") != null;
            }
            else
            {
                this.LogUsage("Use GetCapabilities response");
                supported = capabilities.Analytics != null;
            }
            this.LogAndNotify(Feature.AnalyticsService, "Analytics", supported);
            base.StepPassed();
        }

        private void DefineAudioOutputFeatures()
        {
            AudioOutput[] audioOutputs = null;
            try
            {
                audioOutputs = this.GetAudioOutputs();
            }
            catch (FaultException exception)
            {
                base.StepFailed(exception);
            }
            catch (Exception exception2)
            {
                this.RethrowIfStop(exception2);
                base.LogStepEvent("GetAudioOutputs failed. Assume Audio Output features supported");
                this.LogAssumeSupported("Audio Output");
                this.SetUndefined(this._featuresSet.FindNode(Feature.AudioOutput));
                base.StepFailed(exception2);
                return;
            }
            bool flag = false;
            base.BeginStep("Define Audio Output features");
            if ((audioOutputs == null) || (audioOutputs.Length == 0))
            {
                this.LogAndNotify(Feature.AudioOutput, "Audio Output", false);
                this.TransmitUnsupported(Feature.AudioOutput);
            }
            else
            {
                flag = true;
                this.LogAndNotify(Feature.AudioOutput, "Audio Output", true);
            }
            base.StepPassed();
            if (flag)
            {
                base.LogTestEvent("Check Audio Output sub-features" + Environment.NewLine);
                AudioDecoderConfigurationOptions audioDecoderConfigurationOptions = null;
                try
                {
                    audioDecoderConfigurationOptions = this.GetAudioDecoderConfigurationOptions();
                }
                catch (Exception exception3)
                {
                    this.HandleException(exception3);
                    base.LogStepEvent("GetAudioDecoderConfigurationOptions failed, assume all Audio Output features are supported." + Environment.NewLine);
                    this.TransmitUndefined(Feature.AudioOutput);
                }
                if (audioDecoderConfigurationOptions != null)
                {
                    this.LogAndNotify(Feature.AudioOutputAAC, "AAC", audioDecoderConfigurationOptions.AACDecOptions != null);
                    this.LogAndNotify(Feature.AudioOutputG711, "G711", audioDecoderConfigurationOptions.G711DecOptions != null);
                    this.LogAndNotify(Feature.AudioOutputG726, "G726", audioDecoderConfigurationOptions.G726DecOptions != null);
                }
            }
        }

        private void DefineDeviceFeatures(Capabilities capabilities, DeviceServiceCapabilities serviceCapabilities)
        {
            bool supported = false;
            bool discoveryBye = false;
            bool flag3 = false;
            bool flag4 = false;
            bool flag5 = false;
            bool zeroConfiguration = false;
            bool dynDNS = false;
            bool iPFilter = false;
            bool? nullable = null;
            bool usernameToken = false;
            bool httpDigest = false;
            base.BeginStep("Analyze Device Service capabilities ");
            if (serviceCapabilities != null)
            {
                this.LogUsage("Use GetServiceCapabilities response");
                if (serviceCapabilities.Network != null)
                {
                    if (serviceCapabilities.Network.NTPSpecified)
                    {
                        flag3 = serviceCapabilities.Network.NTP > 0;
                    }
                    else
                    {
                        base.LogStepEvent("NTP not specified");
                    }
                    if (serviceCapabilities.Network.IPVersion6Specified)
                    {
                        flag4 = serviceCapabilities.Network.IPVersion6;
                    }
                    else
                    {
                        base.LogStepEvent("IPv6 support not specified");
                    }
                    if (serviceCapabilities.Network.DHCPv6Specified)
                    {
                        flag5 = serviceCapabilities.Network.DHCPv6;
                    }
                    else
                    {
                        base.LogStepEvent("DHCP v6 support not specified");
                    }
                    if (serviceCapabilities.Network.ZeroConfigurationSpecified)
                    {
                        zeroConfiguration = serviceCapabilities.Network.ZeroConfiguration;
                    }
                    else
                    {
                        base.LogStepEvent("Zero Configuration not specified");
                    }
                    if (serviceCapabilities.Network.DynDNSSpecified)
                    {
                        dynDNS = serviceCapabilities.Network.DynDNS;
                    }
                    else
                    {
                        base.LogStepEvent("Dynamic DNS not specified");
                    }
                    if (serviceCapabilities.Network.IPFilterSpecified)
                    {
                        iPFilter = serviceCapabilities.Network.IPFilter;
                    }
                    else
                    {
                        base.LogStepEvent("IP Filter not specified");
                    }
                }
                else
                {
                    base.LogStepEvent("Network field is empty");
                }
                if (serviceCapabilities.System != null)
                {
                    discoveryBye = serviceCapabilities.System.DiscoveryBye;
                    if (serviceCapabilities.System.SystemLoggingSpecified)
                    {
                        supported = serviceCapabilities.System.SystemLogging;
                    }
                    else
                    {
                        base.LogStepEvent("Logging feature not specified");
                    }
                }
                else
                {
                    base.LogStepEvent("System field is empty");
                }
                if (serviceCapabilities.Security != null)
                {
                    if (serviceCapabilities.Security.UsernameTokenSpecified)
                    {
                        usernameToken = serviceCapabilities.Security.UsernameToken;
                    }
                    else
                    {
                        base.LogStepEvent("WS-Username token feature not specified");
                    }
                    if (serviceCapabilities.Security.HttpDigestSpecified)
                    {
                        httpDigest = serviceCapabilities.Security.HttpDigest;
                    }
                    else
                    {
                        base.LogStepEvent("Digest authentication feature not specified");
                    }
                }
                else
                {
                    base.LogStepEvent("Security field is empty");
                }
                if (capabilities != null)
                {
                    if (capabilities.Device == null)
                    {
                        nullable = false;
                    }
                    else if (capabilities.Device.IO != null)
                    {
                        if (capabilities.Device.IO.RelayOutputsSpecified)
                        {
                            nullable = new bool?(capabilities.Device.IO.RelayOutputs > 0);
                        }
                        else
                        {
                            nullable = false;
                        }
                    }
                    else
                    {
                        nullable = false;
                        base.LogStepEvent("IO field is empty");
                    }
                }
                else
                {
                    nullable = false;
                }
            }
            else
            {
                this.LogUsage("Use GetCapabilities response");
                if (capabilities.Device == null)
                {
                    base.LogStepEvent("Device field is empty");
                }
                else
                {
                    usernameToken = true;
                    if (capabilities.Device.Network != null)
                    {
                        if (capabilities.Device.Network.IPVersion6Specified)
                        {
                            flag4 = capabilities.Device.Network.IPVersion6;
                        }
                        if (capabilities.Device.Network.ZeroConfigurationSpecified)
                        {
                            zeroConfiguration = capabilities.Device.Network.ZeroConfiguration;
                        }
                        if (capabilities.Device.Network.DynDNSSpecified)
                        {
                            dynDNS = capabilities.Device.Network.DynDNS;
                        }
                        if (capabilities.Device.Network.IPFilterSpecified)
                        {
                            iPFilter = capabilities.Device.Network.IPFilter;
                        }
                    }
                    else
                    {
                        base.LogStepEvent("Device.Network field is empty");
                    }
                    if (capabilities.Device.System != null)
                    {
                        supported = capabilities.Device.System.SystemLogging;
                        discoveryBye = capabilities.Device.System.DiscoveryBye;
                    }
                    else
                    {
                        base.LogStepEvent("Device.System field is empty");
                    }
                    if (capabilities.Device.IO != null)
                    {
                        if (capabilities.Device.IO.RelayOutputsSpecified)
                        {
                            nullable = new bool?(capabilities.Device.IO.RelayOutputs > 0);
                        }
                        else
                        {
                            nullable = false;
                        }
                    }
                    else
                    {
                        nullable = false;
                        base.LogStepEvent("IO field is empty");
                    }
                }
            }
            base.StepPassed();
            base.BeginStep("Define Network features");
            if (serviceCapabilities != null)
            {
                this.LogAndNotify(Feature.NTP, "NTP", flag3);
            }
            this.LogAndNotify(Feature.IPv6, "IPv6", flag4);
            this.LogAndNotify(Feature.DHCPv6, "DHCPv6", flag5);
            this.LogAndNotify(Feature.ZeroConfiguration, "Zero Configuration", zeroConfiguration);
            this.LogAndNotify(Feature.DynamicDNS, "Dynamic DNS", dynDNS);
            this.LogAndNotify(Feature.IPFilter, "IP Filter", iPFilter);
            base.StepPassed();
            base.BeginStep("Define Security capabilities");
            this.LogAndNotify(Feature.WSU, "WS-UserName token", usernameToken);
            if (serviceCapabilities != null)
            {
                this.LogAndNotify(Feature.Digest, "Digest", httpDigest);
            }
            base.StepPassed();
            if (serviceCapabilities == null)
            {
                this.CheckDigestSupport();
                this.CheckNTPSupport();
            }
            else if (httpDigest)
            {
                base._credentialsProvider.Security = Security.Digest;
            }
            else
            {
                base._credentialsProvider.Security = Security.WS;
            }
            base.BeginStep("Define Discovery features");
            this.LogAndNotify(Feature.BYE, "Bye message", discoveryBye);
            base.StepPassed();
            base.BeginStep("Define Logging features");
            this.LogAndNotify(Feature.SystemLogging, "Logging", supported);
            base.StepPassed();
            base.BeginStep("Define Device IO features");
            if (nullable.HasValue)
            {
                this.LogAndNotify(Feature.DeviceIORelayOutputs, @"Device Service\IO\Relay Outputs", nullable.Value);
            }
            else
            {
                this.LogAssumeSupported(@"Device Service\IO\Relay Outputs");
                this.SetUndefined(this._featuresSet.FindNode(Feature.DeviceIORelayOutputs));
            }
            base.StepPassed();
            if (nullable.HasValue)
            {
                if (nullable.Value)
                {
                    this.DefineDeviceIOFeatures();
                }
                else
                {
                    this.TransmitUnsupported(Feature.DeviceIORelayOutputs);
                }
            }
        }

        private void DefineDeviceIOFeatures()
        {
            string output;
            RelayOutputSettings outputSettings;
            bool openSupported;
            bool closedSupported;
            Func<RelayOutputSettings, bool> set;
            RelayOutput[] relayOutputs = null;
            try
            {
                relayOutputs = this.GetRelayOutputs();
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
                base.LogTestEvent("GetRelayOutputs failed. Assume all sub-features SUPPORTED ");
                this.SetUndefined(this._featuresSet.FindNode(Feature.DeviceIORelayOutputsBistable));
                this.SetUndefined(this._featuresSet.FindNode(Feature.DeviceIORelayOutputsMonostable));
                return;
            }
            if ((relayOutputs != null) && (relayOutputs.Length != 0))
            {
                output = relayOutputs[0].token;
                outputSettings = new RelayOutputSettings {
                    DelayTime = "PT30S"
                };
                openSupported = false;
                closedSupported = false;
                set = delegate (RelayOutputSettings settings) {
                    try
                    {
                        this.SetRelayOutputSettings(output, settings);
                        return true;
                    }
                    catch (Exception exception)
                    {
                        this.HandleException(exception);
                        return false;
                    }
                };
                Action action = delegate {
                    outputSettings.IdleState = RelayIdleState.closed;
                    closedSupported = set(outputSettings);
                    outputSettings.IdleState = RelayIdleState.open;
                    openSupported = set(outputSettings);
                };
                outputSettings.Mode = RelayMode.Monostable;
                action();
                this.LogAndNotify(Feature.DeviceIORelayOutputsMonostableClosed, @"Device Service\IO\Relay Outputs\Monostable\Closed", closedSupported);
                this.LogAndNotify(Feature.DeviceIORelayOutputsMonostableOpen, @"Device Service\IO\Relay Outputs\Monostable\Open", openSupported);
                this.LogAndNotify(Feature.DeviceIORelayOutputsMonostable, @"Device Service\IO\Relay Outputs\Monostable", openSupported || closedSupported);
                base.LogTestEvent(string.Empty);
                outputSettings.Mode = RelayMode.Bistable;
                action();
                this.LogAndNotify(Feature.DeviceIORelayOutputsBistableClosed, @"Device Service\IO\Relay Outputs\Bistable\Closed", closedSupported);
                this.LogAndNotify(Feature.DeviceIORelayOutputsBistableOpen, @"Device Service\IO\Relay Outputs\Bistable\Open", openSupported);
                this.LogAndNotify(Feature.DeviceIORelayOutputsBistable, @"Device Service\IO\Relay Outputs\Bistable", openSupported || closedSupported);
                base.LogTestEvent(string.Empty);
            }
            else
            {
                base.LogTestEvent("The DUT returned no Relay outputs. Assume all sub-features SUPPORTED");
                this._warning = true;
                this.SetUndefined(this._featuresSet.FindNode(Feature.DeviceIORelayOutputsBistable));
                this.SetUndefined(this._featuresSet.FindNode(Feature.DeviceIORelayOutputsMonostable));
            }
        }

        private void DefineDeviceScopes()
        {
            base.LogTestEvent("Define device scope(s)" + Environment.NewLine);
            if (base._credentialsProvider.Security == Security.None)
            {
                base._credentialsProvider.Security = Security.WS;
            }
            List<string> list = new List<string>();
            TestTool.Proxies.Onvif.Scope[] scopes = null;
            List<string> collection = new List<string>();
            try
            {
                scopes = this.GetScopes();
                if (scopes != null)
                {
                    foreach (TestTool.Proxies.Onvif.Scope scope in scopes)
                    {
                        collection.Add(scope.ScopeItem);
                    }
                }
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
                base.LogTestEvent("Warning: an error occurred during scopes definition" + Environment.NewLine);
                return;
            }
            list.AddRange(collection);
            if (this.ScopeDefined != null)
            {
                foreach (string str in collection)
                {
                    this.ScopeDefined(str);
                }
            }
            base.BeginStep("Check scopes");
            foreach (string str2 in collection)
            {
                base.LogStepEvent(str2);
            }
            base.StepPassed();
        }

        private void DefineHomeFeature(PTZNode node)
        {
            PTZConfiguration configuration;
            PTZConfiguration pTZConfiguration;
            bool flag2;
            Profile profile;
            bool flag3;
            Func<Profile, bool> func = null;
            base.LogTestEvent("Define Fixed/Configurable Home " + Environment.NewLine);
            bool supported = false;
            Action action = delegate {
                this.LogAssumeSupported("PTZ Fixed/Configurable Home");
                this.TransmitUndefined(Feature.PTZHome);
                base.LogStepEvent(string.Empty);
            };
            if (!this._mediaSupported)
            {
                base.LogTestEvent("Media service required - unable to check" + Environment.NewLine);
                this._warning = true;
                action();
                return;
            }
            PTZConfiguration[] ptzConfigurations = null;
            try
            {
                ptzConfigurations = this.GetPtzConfigurations();
                if ((ptzConfigurations != null) && (ptzConfigurations.Length != 0))
                {
                    base.LogTestEvent(string.Empty);
                    configuration = (from C in ptzConfigurations
                        where C.NodeToken == node.token
                        select C).FirstOrDefault<PTZConfiguration>();
                    if (configuration == null)
                    {
                        base.LogTestEvent(string.Format("No PTZ Configuration was found for node {0}. It is impossible to define Fixed/Configurable Home" + Environment.NewLine, this._ptzNode));
                        action();
                        return;
                    }
                    Profile[] profiles = null;
                    try
                    {
                        profiles = this.GetProfiles();
                    }
                    catch (Exception exception2)
                    {
                        this.HandleException(exception2);
                        base.LogTestEvent("Warning: an error occurred getting profiles. It is impossible to define Fixed/Configurable Home feature" + Environment.NewLine);
                        action();
                        return;
                    }
                    pTZConfiguration = null;
                    flag2 = true;
                    profile = null;
                    flag3 = false;
                    if ((profiles != null) && (profiles.Length > 0))
                    {
                        if (func == null)
                        {
                            func = p => (((p.VideoEncoderConfiguration != null) && (p.VideoSourceConfiguration != null)) && (p.PTZConfiguration != null)) && (p.PTZConfiguration.NodeToken == this._ptzNode);
                        }
                        profile = Enumerable.FirstOrDefault<Profile>(profiles, func);
                        if (profile == null)
                        {
                            profile = Enumerable.FirstOrDefault<Profile>(profiles, (Func<Profile, bool>) (p => (((p.VideoEncoderConfiguration != null) && (p.VideoSourceConfiguration != null)) && !p.@fixed)));
                            if (profile == null)
                            {
                                Profile profile2 = Enumerable.FirstOrDefault<Profile>(profiles, (Func<Profile, bool>) (p => ((p.VideoEncoderConfiguration != null) && (p.VideoSourceConfiguration != null))));
                                if (profile2 == null)
                                {
                                    base.LogStepEvent("No valid profile has been found. Skip defining fixed/confugurable Home");
                                    action();
                                    return;
                                }
                                try
                                {
                                    profile = this.CreateProfile("testprofile", "testprofile");
                                    flag3 = true;
                                    flag2 = true;
                                    this.AddVideoSourceConfiguration(profile.token, profile2.VideoSourceConfiguration.token);
                                    this.AddVideoEncoderConfiguration(profile.token, profile2.VideoEncoderConfiguration.token);
                                    goto Label_02E2;
                                }
                                catch (Exception exception3)
                                {
                                    this.HandleException(exception3);
                                    if (exception3 is FaultException)
                                    {
                                        base.LogFault(exception3 as FaultException);
                                    }
                                    base.LogTestEvent("Failed to create or setup profile for test" + Environment.NewLine);
                                    action();
                                    if (flag3)
                                    {
                                        try
                                        {
                                            this.DeleteProfile(profile.token);
                                        }
                                        catch (Exception exception4)
                                        {
                                            this.HandleException(exception4);
                                            base.LogStepEvent("Warning: an error occurred during clean-up actions" + Environment.NewLine);
                                        }
                                    }
                                    return;
                                }
                            }
                            pTZConfiguration = profile.PTZConfiguration;
                        }
                        else
                        {
                            flag2 = false;
                        }
                    }
                    else
                    {
                        base.LogTestEvent("No profiles returned from the DUT" + Environment.NewLine);
                        action();
                        return;
                    }
                    goto Label_02E2;
                }
                base.LogTestEvent("No PTZ configuration returned. It is impossible to define Fixed/Configurable Home feature" + Environment.NewLine);
                this._warning = true;
                action();
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
                base.LogTestEvent("Warning: getting PTZ configurations failed. It is impossible to define Fixed/Configurable Home feature" + Environment.NewLine);
                action();
            }
            return;
        Label_02E2:
            try
            {
                if (flag2)
                {
                    try
                    {
                        this.AddPtzConfiguration(profile.token, configuration.token);
                    }
                    catch (Exception exception5)
                    {
                        this.HandleException(exception5);
                        if (exception5 is FaultException)
                        {
                            base.LogFault(exception5 as FaultException);
                        }
                        base.LogTestEvent("Failed to setup profile for test" + Environment.NewLine);
                        action();
                        return;
                    }
                }
                try
                {
                    this.SetHomePostion(profile.token);
                    supported = true;
                }
                catch (FaultException)
                {
                    base.StepPassed();
                    supported = false;
                }
            }
            catch (Exception exception6)
            {
                this.HandleException(exception6);
                base.LogTestEvent("Warning: an error occurred during defining Fixed/Configurable Home feature." + Environment.NewLine);
                action();
                return;
            }
            finally
            {
                try
                {
                    if (flag3)
                    {
                        this.DeleteProfile(profile.token);
                    }
                    else if (flag2)
                    {
                        if (pTZConfiguration != null)
                        {
                            this.AddPtzConfiguration(profile.token, pTZConfiguration.token);
                        }
                        else
                        {
                            this.RemovePtzConfiguration(profile.token);
                        }
                    }
                }
                catch (Exception exception7)
                {
                    this.HandleException(exception7);
                    base.LogStepEvent("Warning: an error occurred during clean-up actions" + Environment.NewLine);
                }
            }
            this.LogAndNotify(Feature.PTZFixedHome, "Fixed Home", !supported);
            this.LogAndNotify(Feature.PTZConfigurableHome, "Configurable Home", supported);
            base.LogTestEvent(string.Empty);
        }

        private void DefineImagingFeatures(Capabilities capabilities, Service[] services)
        {
            base.BeginStep("Define Imaging features");
            this._imagingSupported = false;
            if (services != null)
            {
                this.LogUsage("Use GetServices response");
                Service service = services.FindService("http://www.onvif.org/ver20/imaging/wsdl");
                this._imagingSupported = service != null;
                if (service != null)
                {
                    this._imagingServiceAddress = service.XAddr;
                }
                else
                {
                    this._imagingServiceAddress = string.Empty;
                }
            }
            else
            {
                this.LogUsage("Use GetCapabilities response");
                this._imagingSupported = capabilities.Imaging != null;
                if (this._imagingSupported)
                {
                    this._imagingServiceAddress = capabilities.Imaging.XAddr;
                }
                else
                {
                    this._imagingServiceAddress = string.Empty;
                }
            }
            this.LogAndNotify(Feature.ImagingService, "Imaging", this._imagingSupported);
            base.StepPassed();
        }

        private void DefineIoCapabilities(Capabilities capabilities, Service[] services)
        {
            Action action2 = null;
            base.BeginStep("Check IO service");
            this._ioSupported = false;
            if (services != null)
            {
                this.LogUsage("Use GetServices response");
                Service service = services.FindService("http://www.onvif.org/ver10/deviceIO/wsdl");
                this._ioSupported = service != null;
                if (service != null)
                {
                    this._ioServiceAddress = service.XAddr;
                }
                else
                {
                    this._ioServiceAddress = string.Empty;
                }
            }
            else
            {
                this.LogUsage("Use GetCapabilities response");
                this._ioSupported = (capabilities.Extension != null) && (capabilities.Extension.DeviceIO != null);
                if (this._ioSupported)
                {
                    this._ioServiceAddress = capabilities.Extension.DeviceIO.XAddr;
                }
                else
                {
                    this._ioServiceAddress = string.Empty;
                }
            }
            this.LogAndNotify(Feature.DeviceIoService, "Device IO Service", this._ioSupported);
            if (!this._ioSupported)
            {
                this.TransmitUnsupported(Feature.DeviceIoService);
                this.FeatureChecked(Feature.RelayOutputs, false);
                this.TransmitUnsupported(Feature.RelayOutputs);
            }
            base.StepPassed();
            if (this._ioSupported)
            {
                if (action2 == null)
                {
                    action2 = delegate {
                        this.LogAssumeSupported("Relay Outputs");
                        this.SetUndefined(this._featuresSet.FindNode(Feature.RelayOutputs));
                    };
                }
                Action action = action2;
                IOServiceCapabilities ioCapabilities = null;
                if (services != null)
                {
                    try
                    {
                        ioCapabilities = this.GetIoCapabilities();
                    }
                    catch (Exception exception)
                    {
                        this.HandleException(exception);
                        base.LogTestEvent("Warning: unable to get Capabilities from IO service" + Environment.NewLine);
                        action();
                        return;
                    }
                    if (ioCapabilities == null)
                    {
                        this._warning = true;
                        base.LogTestEvent("Warning: DUT did not return IO service capabilities" + Environment.NewLine);
                        action();
                        return;
                    }
                }
                base.BeginStep("Define RelayOutputs features");
                bool supported = false;
                if (services != null)
                {
                    this.LogUsage("Use GetServiceCapabilities response");
                    supported = ioCapabilities.RelayOutputs > 0;
                }
                else if (capabilities.Extension != null)
                {
                    if (capabilities.Extension.DeviceIO != null)
                    {
                        supported = capabilities.Extension.DeviceIO.RelayOutputs > 0;
                    }
                    else
                    {
                        base.LogStepEvent("Extension.DeviceIO field is empty");
                    }
                }
                else
                {
                    base.LogStepEvent("Extension field is empty");
                }
                this.LogAndNotify(Feature.RelayOutputs, "Relay outputs", supported);
                base.StepPassed();
            }
        }

        private void DefineMediaFeatures(Capabilities capabilities, Service[] services)
        {
            Action action3 = null;
            Action action4 = null;
            base.BeginStep("Define Media features");
            this._mediaSupported = false;
            if (services != null)
            {
                this.LogUsage("Use GetServices response");
                Service service = services.FindService("http://www.onvif.org/ver10/media/wsdl");
                this._mediaSupported = service != null;
                if (service != null)
                {
                    this._mediaServiceAddress = service.XAddr;
                }
                else
                {
                    this._mediaServiceAddress = string.Empty;
                }
            }
            else
            {
                this.LogUsage("Use GetCapabilities response");
                this._mediaSupported = capabilities.Media != null;
                if (this._mediaSupported)
                {
                    this._mediaServiceAddress = capabilities.Media.XAddr;
                }
                else
                {
                    this._mediaServiceAddress = string.Empty;
                }
            }
            this.LogAndNotify(Feature.MediaService, "Media service", this._mediaSupported);
            if (this._mediaSupported)
            {
                base.LogStepEvent("MANDATORY features: Video, JPEG, RTP/UDP, RTP/RTSP/HTTP");
                this.FeatureDefined(Feature.JPEG, true);
                this.FeatureDefined(Feature.RTPUDP, true);
                this.FeatureDefined(Feature.RTPRTSPHTTP, true);
                base.StepPassed();
                if (action3 == null)
                {
                    action3 = delegate {
                        this.LogAssumeSupported("H.264");
                        this.LogAssumeSupported("MPEG4");
                        this.ReportUndefined(Feature.H264);
                        this.ReportUndefined(Feature.MPEG4);
                        base.LogTestEvent(string.Empty);
                    };
                }
                Action action = action3;
                try
                {
                    VideoEncoderConfigurationOptions videoEncoderConfigurationOptions = this.GetVideoEncoderConfigurationOptions();
                    if (videoEncoderConfigurationOptions != null)
                    {
                        this.LogAndNotify(Feature.H264, "H.264", videoEncoderConfigurationOptions.H264 != null);
                        this.LogAndNotify(Feature.MPEG4, "MPEG4", videoEncoderConfigurationOptions.MPEG4 != null);
                        base.LogTestEvent(string.Empty);
                    }
                    else
                    {
                        base.LogTestEvent("Warning: no Video Encoder configuration options returned." + Environment.NewLine);
                        this._warning = true;
                        action();
                    }
                }
                catch (Exception exception)
                {
                    this.HandleException(exception);
                    base.LogTestEvent("Warning: an error occurred during getting configuration options" + Environment.NewLine);
                    action();
                }
                if (action4 == null)
                {
                    action4 = delegate {
                        this.LogAssumeSupported("Audio");
                        this.SetUndefined(this._featuresSet.FindNode(Feature.Audio));
                    };
                }
                Action action2 = action4;
                try
                {
                    AudioEncoderConfigurationOptions audioEncoderConfigurationOptions = null;
                    try
                    {
                        audioEncoderConfigurationOptions = this.GetAudioEncoderConfigurationOptions();
                        base.BeginStep("Define Audio features");
                        this.FeatureDefined(Feature.Audio, true);
                        base.LogStepEvent("Audio : SUPPORTED");
                        this.FeatureDefined(Feature.G711, true);
                        base.LogStepEvent("MANDATORY feature: G711");
                        AudioEncoderConfigurationOption option = (audioEncoderConfigurationOptions.Options != null) ? Enumerable.FirstOrDefault<AudioEncoderConfigurationOption>(audioEncoderConfigurationOptions.Options, (Func<AudioEncoderConfigurationOption, bool>) (o => (o.Encoding == AudioEncoding.G726))) : null;
                        this.LogAndNotify(Feature.G726, "G726", option != null);
                        AudioEncoderConfigurationOption option2 = (audioEncoderConfigurationOptions.Options != null) ? Enumerable.FirstOrDefault<AudioEncoderConfigurationOption>(audioEncoderConfigurationOptions.Options, (Func<AudioEncoderConfigurationOption, bool>) (o => (o.Encoding == AudioEncoding.AAC))) : null;
                        this.LogAndNotify(Feature.AAC, "AAC", option2 != null);
                        base.StepPassed();
                    }
                    catch (FaultException)
                    {
                        if (base.InStep)
                        {
                            base.StepPassed();
                        }
                        this.FeatureDefined(Feature.Audio, false);
                        base.LogStepEvent("Audio : NOT SUPPORTED" + Environment.NewLine);
                        this.TransmitUnsupported(Feature.Audio);
                    }
                    catch (Exception exception2)
                    {
                        this.HandleException(exception2);
                        base.LogTestEvent("Warning: an error occurred during getting configuration options");
                        action2();
                    }
                    return;
                }
                catch (Exception exception3)
                {
                    this.HandleException(exception3);
                    base.LogTestEvent("Warning: an error occurred during getting configuration options");
                    action2();
                    return;
                }
            }
            base.StepPassed();
            this.TransmitUnsupported(Feature.MediaService);
        }

        private void DefinePtzFeatures(Capabilities capabilities, Service[] services)
        {
            base.BeginStep("Define PTZ service");
            this._ptzSupported = false;
            if (services != null)
            {
                this.LogUsage("Use GetServices response");
                Service service = services.FindService("http://www.onvif.org/ver20/ptz/wsdl");
                this._ptzSupported = service != null;
                if (service != null)
                {
                    this._ptzServiceAddress = service.XAddr;
                }
                else
                {
                    this._ptzServiceAddress = string.Empty;
                }
            }
            else
            {
                this.LogUsage("Use GetCapabilities response");
                this._ptzSupported = capabilities.PTZ != null;
                if (this._ptzSupported)
                {
                    this._ptzServiceAddress = capabilities.PTZ.XAddr;
                }
                else
                {
                    this._ptzServiceAddress = string.Empty;
                }
            }
            this.LogAndNotify(Feature.PTZService, "PTZ Service", this._ptzSupported);
            base.StepPassed();
            if (!this._ptzSupported)
            {
                this.TransmitUnsupported(Feature.PTZService);
            }
            else
            {
                PTZNode ptzNode = null;
                if (!string.IsNullOrEmpty(this._ptzNode))
                {
                    try
                    {
                        ptzNode = this.GetPtzNode();
                    }
                    catch (Exception exception2)
                    {
                        this.HandleException(exception2);
                        this.TransmitUndefined(Feature.PTZService);
                        base.LogStepEvent("GetNode failed");
                        base.LogStepEvent("Assume all PTZ features are supported" + Environment.NewLine);
                        return;
                    }
                    if (ptzNode == null)
                    {
                        this.TransmitUndefined(Feature.PTZService);
                        base.LogStepEvent(string.Format("No information has been received for node with token {0}. Assume all PTZ features are supported" + Environment.NewLine, this._ptzNode));
                        return;
                    }
                }
                else
                {
                    base.LogTestEvent("Note: no node for testing was selected. Testing will be performed for the first node in list.");
                    base.LogTestEvent(string.Empty);
                    PTZNode[] ptzNodes = null;
                    try
                    {
                        ptzNodes = this.GetPtzNodes();
                    }
                    catch (Exception exception)
                    {
                        this.HandleException(exception);
                        this.TransmitUndefined(Feature.PTZService);
                        base.LogStepEvent("GetNodes failed");
                        base.LogStepEvent("Assume all PTZ features are supported" + Environment.NewLine);
                        return;
                    }
                    if ((ptzNodes != null) && (ptzNodes.Length > 0))
                    {
                        ptzNode = ptzNodes[0];
                        base.LogTestEvent(string.Format("Use node with token {0}", ptzNode.token));
                        base.LogTestEvent(string.Empty);
                    }
                    else
                    {
                        this.TransmitUndefined(Feature.PTZService);
                        base.LogStepEvent("No PTZ node for test were found. Assume all PTZ features are supported" + Environment.NewLine);
                        return;
                    }
                }
                base.BeginStep("Define PTZ Features");
                bool supported = false;
                bool flag2 = false;
                bool flag3 = false;
                bool flag4 = false;
                bool flag5 = false;
                bool flag6 = false;
                bool flag7 = false;
                bool flag8 = false;
                bool flag9 = false;
                bool homeSupported = false;
                bool flag11 = false;
                if (ptzNode.SupportedPTZSpaces != null)
                {
                    supported = this.CheckPTZSpaces<Space2DDescription>(ptzNode.SupportedPTZSpaces.AbsolutePanTiltPositionSpace);
                    flag2 = this.CheckPTZSpaces<Space1DDescription>(ptzNode.SupportedPTZSpaces.AbsoluteZoomPositionSpace);
                    flag3 = this.CheckPTZSpaces<Space2DDescription>(ptzNode.SupportedPTZSpaces.RelativePanTiltTranslationSpace);
                    flag4 = this.CheckPTZSpaces<Space1DDescription>(ptzNode.SupportedPTZSpaces.RelativeZoomTranslationSpace);
                    flag5 = this.CheckPTZSpaces<Space2DDescription>(ptzNode.SupportedPTZSpaces.ContinuousPanTiltVelocitySpace);
                    flag6 = this.CheckPTZSpaces<Space1DDescription>(ptzNode.SupportedPTZSpaces.ContinuousZoomVelocitySpace);
                    flag7 = this.CheckPTZSpaces<Space1DDescription>(ptzNode.SupportedPTZSpaces.PanTiltSpeedSpace);
                    flag8 = this.CheckPTZSpaces<Space1DDescription>(ptzNode.SupportedPTZSpaces.ZoomSpeedSpace);
                }
                flag9 = ptzNode.MaximumNumberOfPresets > 0;
                homeSupported = ptzNode.HomeSupported;
                flag11 = (ptzNode.AuxiliaryCommands != null) && (ptzNode.AuxiliaryCommands.Length > 0);
                this.LogAndNotify(Feature.PTZAbsolute, "Absolute", supported || flag2);
                this.LogAndNotify(Feature.PTZAbsolutePanTilt, "Absolute Pan/Tilt", supported);
                this.LogAndNotify(Feature.PTZAbsoluteZoom, "Absolute Zoom", flag2);
                this.LogAndNotify(Feature.PTZRelative, "Relative", flag3 || flag4);
                this.LogAndNotify(Feature.PTZRelativePanTilt, "Relative Pan/Tilt", flag3);
                this.LogAndNotify(Feature.PTZRelativeZoom, "Relative Zoom", flag4);
                base.LogStepEvent(string.Format("Absolute or relative: {0}", ((supported || flag2) || (flag3 || flag4)) ? "SUPPORTED" : "NOT SUPPORTED"));
                base.LogStepEvent("Continuous move is MANDATORY");
                this.FeatureChecked(Feature.PTZContinious, true);
                this.LogAndNotify(Feature.PTZContinuousPanTilt, "Continuous Pan/Tilt", flag5);
                this.LogAndNotify(Feature.PTZContinuousZoom, "Continuous Zoom", flag6);
                this.LogAndNotify(Feature.PTZSpeed, "Speed", flag7 || flag8);
                this.LogAndNotify(Feature.PTZSpeedPanTilt, "Speed Pan/Tilt", flag7);
                this.LogAndNotify(Feature.PTZSpeedZoom, "Speed Zoom", flag8);
                this.LogAndNotify(Feature.PTZPresets, "Presets", flag9);
                this.LogAndNotify(Feature.PTZHome, "Home position", homeSupported);
                this.LogAndNotify(Feature.PTZAuxiliary, "Auxilliary", flag11);
                base.StepPassed();
                if (homeSupported)
                {
                    this.DefineHomeFeature(ptzNode);
                }
                else
                {
                    this.TransmitUnsupported(Feature.PTZHome);
                }
            }
        }

        private void DefineReceiverCapabilities(Capabilities capabilities, Service[] services)
        {
            base.BeginStep("Define Receiver service support");
            if (services != null)
            {
                this._receiverSupported = Enumerable.Count<Service>(services, (Func<Service, bool>) (S => (S.Namespace.ToLower() == "http://www.onvif.org/ver10/receiver/wsdl"))) > 0;
                if (this._receiverSupported)
                {
                    Service service = Enumerable.FirstOrDefault<Service>(Enumerable.ThenByDescending<Service, int>(Enumerable.OrderByDescending<Service, int>(services, delegate (Service s) {
                        if (s.Version != null)
                        {
                            return s.Version.Major;
                        }
                        return 0;
                    }), delegate (Service s) {
                        if (s.Version != null)
                        {
                            return s.Version.Minor;
                        }
                        return 0;
                    }), (Func<Service, bool>) (s => (s.Namespace.ToLower() == "http://www.onvif.org/ver10/receiver/wsdl")));
                    this._receiverServiceAddress = service.XAddr;
                }
            }
            else
            {
                this._receiverSupported = (capabilities.Extension != null) && (capabilities.Extension.Receiver != null);
                if (this._receiverSupported)
                {
                    this._receiverServiceAddress = capabilities.Extension.Receiver.XAddr;
                }
            }
            this.LogAndNotify(Feature.ReceiverService, "Receiver service", this._receiverSupported);
            base.StepPassed();
        }

        private void DefineRecordingCapabilities(Capabilities capabilities, Service[] services)
        {
            base.BeginStep("Define Recording Control service support");
            if (services != null)
            {
                this._recordingControlSupported = Enumerable.Count<Service>(services, (Func<Service, bool>) (S => (S.Namespace.ToLower() == "http://www.onvif.org/ver10/recording/wsdl"))) > 0;
                if (this._recordingControlSupported)
                {
                    Service service = Enumerable.FirstOrDefault<Service>(Enumerable.ThenByDescending<Service, int>(Enumerable.OrderByDescending<Service, int>(services, delegate (Service s) {
                        if (s.Version != null)
                        {
                            return s.Version.Major;
                        }
                        return 0;
                    }), delegate (Service s) {
                        if (s.Version != null)
                        {
                            return s.Version.Minor;
                        }
                        return 0;
                    }), (Func<Service, bool>) (s => (s.Namespace.ToLower() == "http://www.onvif.org/ver10/recording/wsdl")));
                    this._recordingControlServiceAddress = service.XAddr;
                }
            }
            else
            {
                this._recordingControlSupported = (capabilities.Extension != null) && (capabilities.Extension.Recording != null);
                if (this._recordingControlSupported)
                {
                    this._recordingControlServiceAddress = capabilities.Extension.Recording.XAddr;
                }
            }
            this.LogAndNotify(Feature.RecordingControlService, "Recording Control service", this._recordingControlSupported);
            base.StepPassed();
            if (this._recordingControlSupported)
            {
                if (services == null)
                {
                    RecordingCapabilities recording = capabilities.Extension.Recording;
                    this.LogAndNotify(Feature.DynamicRecording, "Dynamic recording", recording.DynamicRecordings);
                    this.LogAndNotify(Feature.ProfileAsSource, "Profile as Source", recording.MediaProfileSource);
                    this.LogAndNotify(Feature.ReceiverAsSource, "Receiver as Source", recording.ReceiverSource);
                    this.LogAndNotify(Feature.DynamicTracks, "Dynamic tracks", recording.DynamicTracks);
                    bool supported = false;
                    this.LogAndNotify(Feature.AudioRecording, "Audio Recording", supported);
                    base.LogStepEvent(string.Empty);
                }
                else
                {
                    try
                    {
                        RecordingServiceCapabilities recordingServiceCapabilities = this.GetRecordingServiceCapabilities();
                        this.LogAndNotify(Feature.DynamicRecording, "Dynamic recording", recordingServiceCapabilities.DynamicRecordingsSpecified && recordingServiceCapabilities.DynamicRecordings);
                        this.LogAndNotify(Feature.DynamicTracks, "Dynamic tracks", recordingServiceCapabilities.DynamicTracksSpecified && recordingServiceCapabilities.DynamicTracks);
                        string[] encoding = recordingServiceCapabilities.Encoding;
                        bool flag = (encoding.Contains<string>(AudioEncoding.AAC.ToString()) || encoding.Contains<string>(AudioEncoding.G711.ToString())) || encoding.Contains<string>(AudioEncoding.G726.ToString());
                        this.LogAndNotify(Feature.AudioRecording, "Audio Recording", flag);
                        base.LogStepEvent(string.Empty);
                    }
                    catch (Exception exception)
                    {
                        if (base.InStep)
                        {
                            base.StepPassed();
                        }
                        this.HandleException(exception);
                        base.LogTestEvent(string.Format("Warning: an error occurred during getting Recording Service Capabilities{0}", Environment.NewLine));
                        this.LogAssumeSupported("Dynamic Recording");
                        this.ReportUndefined(Feature.DynamicRecording);
                        this.LogAssumeSupported("Dynamic Tracks");
                        this.ReportUndefined(Feature.DynamicTracks);
                        this.LogAssumeSupported("Audio Recording");
                        this.ReportUndefined(Feature.AudioRecording);
                        base.LogStepEvent(string.Empty);
                    }
                }
            }
            else
            {
                this.LogAndNotify(Feature.DynamicRecording, "Dynamic recording", false);
                this.LogAndNotify(Feature.DynamicTracks, "Dynamic tracks", false);
                this.LogAndNotify(Feature.AudioRecording, "Audio Recording", false);
                base.LogStepEvent(string.Empty);
            }
        }

        private void DefineReplayCapabilities(Capabilities capabilities, Service[] services)
        {
            base.BeginStep("Define Replay service support");
            if (services != null)
            {
                this._replaySupported = Enumerable.Count<Service>(services, (Func<Service, bool>) (S => (S.Namespace.ToLower() == "http://www.onvif.org/ver10/replay/wsdl"))) > 0;
                if (this._replaySupported)
                {
                    Service service = Enumerable.FirstOrDefault<Service>(Enumerable.ThenByDescending<Service, int>(Enumerable.OrderByDescending<Service, int>(services, delegate (Service s) {
                        if (s.Version != null)
                        {
                            return s.Version.Major;
                        }
                        return 0;
                    }), delegate (Service s) {
                        if (s.Version != null)
                        {
                            return s.Version.Minor;
                        }
                        return 0;
                    }), (Func<Service, bool>) (s => (s.Namespace.ToLower() == "http://www.onvif.org/ver10/replay/wsdl")));
                    this._replayServiceAddress = service.XAddr;
                }
            }
            else
            {
                this._replaySupported = (capabilities.Extension != null) && (capabilities.Extension.Replay != null);
                if (this._replaySupported)
                {
                    this._replayServiceAddress = capabilities.Extension.Replay.XAddr;
                }
            }
            this.LogAndNotify(Feature.ReplayService, "Replay service", this._replaySupported);
            base.StepPassed();
            if (this._replaySupported)
            {
                if (services != null)
                {
                    try
                    {
                        ReplayServiceCapabilities replayServiceCapabilities = this.GetReplayServiceCapabilities();
                        this.LogAndNotify(Feature.ReverseReplay, "Reverse Replay", replayServiceCapabilities.ReversePlayback);
                        base.LogStepEvent(string.Empty);
                    }
                    catch (Exception exception)
                    {
                        this.HandleException(exception);
                        base.LogTestEvent(string.Format("Warning: an error occurred during getting Replay Service Capabilities{0}", Environment.NewLine));
                        this.LogAssumeSupported("Reverse Replay");
                        this.ReportUndefined(Feature.ReverseReplay);
                    }
                }
            }
            else
            {
                this.TransmitUnsupported(Feature.ReplayService);
            }
        }

        private void DefineSearchCapabilities(Capabilities capabilities, Service[] services)
        {
            base.BeginStep("Define Search service support");
            if (services != null)
            {
                this._searchSupported = Enumerable.Count<Service>(services, (Func<Service, bool>) (S => (S.Namespace.ToLower() == "http://www.onvif.org/ver10/search/wsdl"))) > 0;
                if (this._searchSupported)
                {
                    Service service = Enumerable.FirstOrDefault<Service>(Enumerable.ThenByDescending<Service, int>(Enumerable.OrderByDescending<Service, int>(services, delegate (Service s) {
                        if (s.Version != null)
                        {
                            return s.Version.Major;
                        }
                        return 0;
                    }), delegate (Service s) {
                        if (s.Version != null)
                        {
                            return s.Version.Minor;
                        }
                        return 0;
                    }), (Func<Service, bool>) (s => (s.Namespace.ToLower() == "http://www.onvif.org/ver10/search/wsdl")));
                    this._searchServiceAddress = service.XAddr;
                }
            }
            else
            {
                this._searchSupported = (capabilities.Extension != null) && (capabilities.Extension.Search != null);
                if (this._searchSupported)
                {
                    this._searchServiceAddress = capabilities.Extension.Search.XAddr;
                }
            }
            this.LogAndNotify(Feature.RecordingSearchService, "Search service", this._searchSupported);
            base.StepPassed();
            Action action = delegate {
                this.LogAssumeSupported("Metadata Recording");
                this.ReportUndefined(Feature.MetadataRecording);
                this.LogAssumeSupported("PTZ Position Search");
                this.ReportUndefined(Feature.PTZPositionSearch);
                base.LogStepEvent(string.Empty);
            };
            if (this._searchSupported)
            {
                if (services != null)
                {
                    SearchServiceCapabilities searchServiceCapabilities = null;
                    try
                    {
                        searchServiceCapabilities = this.GetSearchServiceCapabilities();
                        this.LogAndNotify(Feature.MetadataSearch, "Metadata Search", searchServiceCapabilities.MetadataSearchSpecified && searchServiceCapabilities.MetadataSearch);
                    }
                    catch (Exception exception)
                    {
                        this.HandleException(exception);
                        base.LogTestEvent("Warning: an error occurred during getting Search service capabilities" + Environment.NewLine);
                        this.LogAssumeSupported("Metadata Search");
                        this.ReportUndefined(Feature.MetadataSearch);
                    }
                    base.LogStepEvent(string.Empty);
                }
                else
                {
                    this.LogAndNotify(Feature.MetadataSearch, "Metadata Search", capabilities.Extension.Search.MetadataSearch);
                    base.LogStepEvent(string.Empty);
                }
                try
                {
                    RecordingInformation recordingInformation = this.GetRecordingInformation(this._recordingToken);
                    if (recordingInformation != null)
                    {
                        bool supported = false;
                        if (recordingInformation.Track != null)
                        {
                            TrackInformation information2 = (from T in recordingInformation.Track
                                where T.TrackType == TrackType.Metadata
                                select T).FirstOrDefault<TrackInformation>();
                            supported = (information2 != null) && (information2.DataFrom < information2.DataTo);
                        }
                        this.LogAndNotify(Feature.MetadataRecording, "Metadata Recording", supported);
                        base.LogTestEvent(string.Empty);
                        string searchToken = null;
                        try
                        {
                            System.DateTime? endPoint = null;
                            if (recordingInformation.LatestRecordingSpecified)
                            {
                                endPoint = new System.DateTime?(recordingInformation.LatestRecording);
                            }
                            SearchScope scope = new SearchScope();
                            PTZPositionFilter searchFilter = new PTZPositionFilter {
                                MinPosition = new PTZVector()
                            };
                            Vector2D vectord = new Vector2D {
                                x = -1f,
                                y = -1f
                            };
                            searchFilter.MinPosition.PanTilt = vectord;
                            searchFilter.MaxPosition = new PTZVector();
                            Vector2D vectord2 = new Vector2D {
                                x = 1f,
                                y = 1f
                            };
                            searchFilter.MaxPosition.PanTilt = vectord2;
                            searchToken = this.FindPTZPosition(recordingInformation.EarliestRecording, endPoint, scope, searchFilter, null, "PT3S").SearchToken;
                            this.LogAndNotify(Feature.PTZPositionSearch, "PTZPositionSearch", true);
                            base.LogTestEvent(string.Empty);
                        }
                        catch (FaultException exception2)
                        {
                            this.HandleException(exception2);
                            this.LogAndNotify(Feature.PTZPositionSearch, "PTZPositionSearch", false);
                            base.LogTestEvent(string.Empty);
                        }
                        catch (Exception exception3)
                        {
                            this.HandleException(exception3);
                            base.LogTestEvent("Warning: an error occurred during sending FindPTZPosition request" + Environment.NewLine);
                            this.LogAssumeSupported("PTZ Position Search");
                            this.ReportUndefined(Feature.PTZPositionSearch);
                        }
                        if (string.IsNullOrEmpty(searchToken))
                        {
                            return;
                        }
                        try
                        {
                            this.StopPTZPositionSearch(searchToken);
                            return;
                        }
                        catch (Exception exception4)
                        {
                            this.HandleException(exception4);
                            return;
                        }
                    }
                    base.LogTestEvent(string.Format("No RecordingInformaton returned for token='{0}'{1}", this._recordingToken, Environment.NewLine));
                    action();
                }
                catch (Exception exception5)
                {
                    this.HandleException(exception5);
                    base.LogTestEvent(string.Format("Warning: an error occurred during getting RecordingInformation for token='{0}'{1}", this._recordingToken, Environment.NewLine));
                    action();
                }
            }
            else
            {
                this.TransmitUnsupported(Feature.RecordingSearchService);
                this.LogAndNotify(Feature.MetadataRecording, "Metadata Recording", false);
            }
        }

        private void DefineSnapshotURIFeature()
        {
            base.LogTestEvent("Define GetSnapshotURI capability" + Environment.NewLine);
            bool supported = false;
            bool flag2 = false;
            Action action = delegate {
                this.LogAssumeSupported("Snapshot URI");
                base.LogTestEvent(string.Empty);
                this.SetUndefined(this._featuresSet.FindNode(Feature.SnapshotUri));
            };
            Profile[] profiles = null;
            try
            {
                profiles = this.GetProfiles();
            }
            catch (Exception exception)
            {
                this.HandleException(exception);
                base.LogTestEvent("Warning: an error occurred during getting profiles. It is impossible to define GetSnapshotURI capability" + Environment.NewLine);
                action();
                return;
            }
            Profile profile = null;
            base.LogTestEvent("Find profile with Video Source and Video Encoder for testing Snapshot URI feature" + Environment.NewLine);
            if ((profiles != null) && (profiles.Length > 0))
            {
                profile = Enumerable.FirstOrDefault<Profile>(profiles, (Func<Profile, bool>) (P => ((P.VideoEncoderConfiguration != null) && (P.VideoSourceConfiguration != null))));
            }
            if (profile != null)
            {
                base.LogTestEvent("Use profile with token " + profile.token + Environment.NewLine);
                try
                {
                    this.GetSnapshotUri(profile.token);
                    supported = true;
                }
                catch (FaultException)
                {
                    base.StepPassed();
                    supported = false;
                }
                catch (Exception exception2)
                {
                    this.HandleException(exception2);
                    flag2 = true;
                    base.LogTestEvent("Warning: an error occurred during defining Snapshot URI feature. " + Environment.NewLine);
                    action();
                }
                if (!flag2)
                {
                    this.LogAndNotify(Feature.SnapshotUri, "GetSnapshotUri", supported);
                }
                base.LogTestEvent(string.Empty);
            }
            else
            {
                base.LogTestEvent("Failed to find profile for testing. It is impossible to define GetSnapshotUri capability" + Environment.NewLine);
                action();
            }
        }

        private void DefineStreamingCapabilities(Capabilities capabilities, MediaServiceCapabilities mediaCapabilities)
        {
            base.BeginStep("Define Streaming features");
            if (mediaCapabilities != null)
            {
                this.LogUsage("Use GetServiceCapabilities response");
                bool supported = false;
                bool flag2 = false;
                if (mediaCapabilities.StreamingCapabilities != null)
                {
                    if (mediaCapabilities.StreamingCapabilities.RTP_RTSP_TCPSpecified)
                    {
                        flag2 = mediaCapabilities.StreamingCapabilities.RTP_RTSP_TCP;
                    }
                    if (mediaCapabilities.StreamingCapabilities.RTPMulticastSpecified)
                    {
                        supported = mediaCapabilities.StreamingCapabilities.RTPMulticast;
                    }
                }
                else
                {
                    base.LogStepEvent("StreamingCapabilities field is empty");
                }
                this.LogAndNotify(Feature.RTPRTSPTCP, "RTP/RTSP/TCP", flag2);
                this.LogAndNotify(Feature.RTPMulticastUDP, "RTPMulticast/UDP", supported);
            }
            else
            {
                bool rTPMulticast = false;
                bool flag4 = false;
                if (capabilities.Media != null)
                {
                    if (capabilities.Media.StreamingCapabilities != null)
                    {
                        if (capabilities.Media.StreamingCapabilities.RTP_RTSP_TCPSpecified)
                        {
                            flag4 = capabilities.Media.StreamingCapabilities.RTP_RTSP_TCP;
                        }
                        if (capabilities.Media.StreamingCapabilities.RTPMulticastSpecified)
                        {
                            rTPMulticast = capabilities.Media.StreamingCapabilities.RTPMulticast;
                        }
                    }
                    else
                    {
                        base.LogStepEvent("Media.StreamingCapabilities field is empty");
                    }
                }
                else
                {
                    base.LogStepEvent("Media field is empty");
                }
                this.LogAndNotify(Feature.RTPRTSPTCP, "RTP/RTSP/TCP", flag4);
                this.LogAndNotify(Feature.RTPMulticastUDP, "RTPMulticast/UDP", rTPMulticast);
            }
            base.StepPassed();
            if (this._mediaSupported)
            {
                this.DefineSnapshotURIFeature();
            }
        }

        protected void DeleteProfile(string token)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            base.RunStep(() => client.DeleteProfile(token), string.Format(string.Format("Delete profile {0}", token), new object[0]));
            base.DoRequestDelay();
        }

        private void FeatureChecked(Feature feature, bool supported)
        {
            this.ReportFeatureDefined(feature, supported);
            if (supported)
            {
                this._features.Add(feature);
            }
        }

        private FindPTZPositionResponse FindPTZPosition(System.DateTime startPoint, System.DateTime? endPoint, SearchScope scope, PTZPositionFilter searchFilter, int? maxMatches, string keepAliveTime)
        {
            FindPTZPositionResponse response = null;
            SearchPortClient client = this.SearchClient;
            base.RunStep(delegate {
                response = client.FindPTZPosition(startPoint, endPoint, scope, searchFilter, maxMatches, keepAliveTime);
            }, "Send FindPTZPosition request");
            base.DoRequestDelay();
            return response;
        }

        protected AudioDecoderConfigurationOptions GetAudioDecoderConfigurationOptions()
        {
            TestTool.Proxies.Onvif.MediaClient mediaClient = this.MediaClient;
            AudioDecoderConfigurationOptions options = null;
            base.RunStep(delegate {
                options = mediaClient.GetAudioDecoderConfigurationOptions(null, null);
            }, "Get Audio Decoder Configuration Options");
            base.DoRequestDelay();
            return options;
        }

        protected AudioEncoderConfigurationOptions GetAudioEncoderConfigurationOptions()
        {
            TestTool.Proxies.Onvif.MediaClient mediaClient = this.MediaClient;
            AudioEncoderConfigurationOptions options = null;
            base.RunStep(delegate {
                options = mediaClient.GetAudioEncoderConfigurationOptions(null, null);
            }, "Get Audio Encoder Configuration Options");
            base.DoRequestDelay();
            return options;
        }

        protected AudioOutput[] GetAudioOutputs()
        {
            TestTool.Proxies.Onvif.MediaClient mediaClient = this.MediaClient;
            AudioOutput[] outputs = null;
            base.RunStep(delegate {
                outputs = mediaClient.GetAudioOutputs();
            }, "Get Audio Outputs");
            base.DoRequestDelay();
            return outputs;
        }

        protected Capabilities GetCapabilities(CapabilityCategory[] categories)
        {
            return this.GetCapabilities(categories, "Get capabilities");
        }

        protected Capabilities GetCapabilities(CapabilityCategory[] categories, string stepName)
        {
            Capabilities capabilities = null;
            bool flag = false;
            base.BeginStep("GetCapabilities (no credentials supplied)");
            try
            {
                capabilities = base.Client.GetCapabilities(categories);
            }
            catch (AccessDeniedException)
            {
                base._credentialsProvider.Security = Security.Digest;
                base.LogStepEvent("DUT requires Digest authentication");
                base.LogStepEvent("Warning: GetCapabilities should not require authentication");
                flag = true;
            }
            catch (FaultException exception)
            {
                base.LogFault(exception);
                if (this.IsAccessDeniedFault(exception))
                {
                    base._credentialsProvider.Security = Security.WS;
                    base.LogStepEvent("DUT requires WS-UsernameToken authentication");
                    base.LogStepEvent("Warning: GetCapabilities should not require authentication");
                    flag = true;
                }
            }
            catch (Exception exception2)
            {
                this.RethrowIfStop(exception2);
                base.LogStepEvent(string.Format("GetCapabilities failed ({0})", exception2.Message));
            }
            base.StepPassed();
            base.DoRequestDelay();
            if (flag)
            {
                base.BeginStep("Get Capabilities");
                try
                {
                    capabilities = base.Client.GetCapabilities(categories);
                }
                catch (FaultException exception3)
                {
                    base.LogFault(exception3);
                    base.LogStepEvent(string.Format("GetCapabilities failed ({0})", exception3.Message));
                }
                catch (Exception exception4)
                {
                    this.RethrowIfStop(exception4);
                    base.LogStepEvent(string.Format("GetCapabilities failed ({0})", exception4.Message));
                }
                base.StepPassed();
                base.DoRequestDelay();
            }
            return capabilities;
        }

        protected VideoSourceConfiguration[] GetCompatibleVideoSourceConfigurations(string profile)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            VideoSourceConfiguration[] configs = null;
            base.RunStep(delegate {
                configs = client.GetCompatibleVideoSourceConfigurations(profile);
            }, string.Format("Get compatible video sources for profile '{0}'", profile));
            base.DoRequestDelay();
            return configs;
        }

        private DeviceInformation GetDeviceInformation()
        {
            DeviceInformation information = new DeviceInformation();
            string str = null;
            string model = null;
            string firmwareVersion = null;
            string serialNumber = null;
            string hardwareId = null;
            bool flag = false;
            bool flag2 = false;
            if (base._credentialsProvider.Security == Security.None)
            {
                base.BeginStep("Get device information (no credentials supplied)");
                try
                {
                    str = base.Client.GetDeviceInformation(out model, out firmwareVersion, out serialNumber, out hardwareId);
                }
                catch (AccessDeniedException)
                {
                    base._credentialsProvider.Security = Security.Digest;
                    base.LogStepEvent("DUT requires Digest authentication");
                    flag = true;
                }
                catch (FaultException exception)
                {
                    base.LogFault(exception);
                    if (this.IsAccessDeniedFault(exception))
                    {
                        base._credentialsProvider.Security = Security.WS;
                        base.LogStepEvent("DUT requires WS-UsernameToken authentication");
                        flag = true;
                    }
                    else
                    {
                        base.LogStepEvent(string.Format("Get device information failed ({0})", exception.Message));
                        flag2 = true;
                    }
                }
                catch (Exception exception2)
                {
                    this.RethrowIfStop(exception2);
                    base.LogStepEvent(string.Format("Get device information failed ({0})", exception2.Message));
                    flag2 = true;
                }
                base.StepPassed();
                base.DoRequestDelay();
                if (flag2)
                {
                    return information;
                }
            }
            else
            {
                flag = true;
            }
            if (flag)
            {
                base.BeginStep("Get device information");
                try
                {
                    str = base.Client.GetDeviceInformation(out model, out firmwareVersion, out serialNumber, out hardwareId);
                }
                catch (Exception exception3)
                {
                    if (exception3 is FaultException)
                    {
                        base.LogFault(exception3 as FaultException);
                    }
                    this.RethrowIfStop(exception3);
                    base.LogStepEvent(string.Format("Get device information failed ({0})", exception3.Message));
                }
                base.StepPassed();
                base.DoRequestDelay();
            }
            information.FirmwareVersion = firmwareVersion;
            information.HardwareID = hardwareId;
            information.Manufacturer = str;
            information.Model = model;
            information.SerialNumber = serialNumber;
            return information;
        }

        protected IOServiceCapabilities GetIoCapabilities()
        {
            Action action = null;
            DeviceIOPortClient client = this.IoClient;
            if (client == null)
            {
                return null;
            }
            IOServiceCapabilities capabilities = null;
            try
            {
                if (action == null)
                {
                    action = delegate {
                        capabilities = client.GetServiceCapabilities();
                    };
                }
                base.RunStep(action, "Get IO capabilities");
            }
            catch (Exception exception)
            {
                this.RethrowIfStop(exception);
                base.LogStepEvent(string.Format("GetServiceCapabilities not supported ({0})", exception.Message));
                base.StepPassed();
            }
            base.DoRequestDelay();
            return capabilities;
        }

        protected MediaServiceCapabilities GetMediaCapabilities()
        {
            Action action = null;
            GetServiceCapabilitiesResponse capabilities;
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            if (client != null)
            {
                capabilities = null;
                try
                {
                    if (action == null)
                    {
                        action = delegate {
                            capabilities = client.GetServiceCapabilities(new TestTool.Proxies.Onvif.GetServiceCapabilities());
                        };
                    }
                    base.RunStep(action, "Get Media Capabilities");
                }
                catch (Exception exception)
                {
                    if (exception is FaultException)
                    {
                        base.LogFault(exception as FaultException);
                    }
                    this.RethrowIfStop(exception);
                    base.LogStepEvent(string.Format("GetServiceCapabilities not supported ({0})", exception.Message));
                    base.StepPassed();
                }
                base.DoRequestDelay();
                if (capabilities != null)
                {
                    return capabilities.Capabilities;
                }
            }
            return null;
        }

        protected NTPInformation GetNTP()
        {
            NTPInformation ntp = null;
            base.RunStep(delegate {
                ntp = this.Client.GetNTP();
            }, "Get NTP Information");
            base.DoRequestDelay();
            return ntp;
        }

        protected Profile[] GetProfiles()
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            if (client == null)
            {
                return null;
            }
            Profile[] profiles = null;
            base.RunStep(delegate {
                profiles = client.GetProfiles();
            }, "Get Profiles");
            base.DoRequestDelay();
            return profiles;
        }

        protected PTZConfiguration[] GetPtzConfigurations()
        {
            PTZClient client = this.PtzClient;
            PTZConfiguration[] configurations = null;
            base.RunStep(delegate {
                configurations = client.GetConfigurations();
            }, "Get PTZ Configurations");
            base.DoRequestDelay();
            if (configurations != null)
            {
                base.LogStepEvent(string.Format("{0} configurations found", configurations.Length));
            }
            return configurations;
        }

        protected PTZNode GetPtzNode()
        {
            PTZClient client = this.PtzClient;
            PTZNode node = null;
            base.RunStep(delegate {
                node = client.GetNode(this._ptzNode);
            }, "Get PTZ Node");
            base.DoRequestDelay();
            return node;
        }

        protected PTZNode[] GetPtzNodes()
        {
            PTZClient client = this.PtzClient;
            PTZNode[] nodes = null;
            base.RunStep(delegate {
                nodes = client.GetNodes();
            }, "Get PTZ Nodes");
            base.DoRequestDelay();
            return nodes;
        }

        private RecordingInformation GetRecordingInformation(string token)
        {
            RecordingInformation info = null;
            SearchPortClient client = this.SearchClient;
            base.RunStep(delegate {
                info = client.GetRecordingInformation(token);
            }, string.Format("Get recording information (token = '{0}')", token));
            base.DoRequestDelay();
            return info;
        }

        protected GetRecordingsResponseItem[] GetRecordings()
        {
            RecordingPortClient recordingClient = this.RecordingClient;
            GetRecordingsResponseItem[] response = null;
            base.RunStep(delegate {
                response = this.RecordingClient.GetRecordings();
            }, "Get Recordings");
            base.DoRequestDelay();
            return response;
        }

        protected RecordingServiceCapabilities GetRecordingServiceCapabilities()
        {
            RecordingServiceCapabilities response = null;
            base.RunStep(delegate {
                response = this.RecordingClient.GetServiceCapabilities();
            }, "Get Recording service capabilities");
            base.DoRequestDelay();
            return response;
        }

        protected RelayOutput[] GetRelayOutputs()
        {
            RelayOutput[] outputs = null;
            base.RunStep(delegate {
                outputs = this.Client.GetRelayOutputs();
            }, "Get Relay Outputs");
            base.DoRequestDelay();
            return outputs;
        }

        protected ReplayServiceCapabilities GetReplayServiceCapabilities()
        {
            ReplayServiceCapabilities response = null;
            base.RunStep(delegate {
                response = this.ReplayClient.GetServiceCapabilities();
            }, "Get Replay service capabilities");
            base.DoRequestDelay();
            return response;
        }

        protected TestTool.Proxies.Onvif.Scope[] GetScopes()
        {
            TestTool.Proxies.Onvif.Scope[] response = null;
            base.RunStep(delegate {
                response = this.Client.GetScopes();
            }, "Get device scopes");
            base.DoRequestDelay();
            return response;
        }

        protected SearchServiceCapabilities GetSearchServiceCapabilities()
        {
            SearchServiceCapabilities response = null;
            base.RunStep(delegate {
                response = this.SearchClient.GetServiceCapabilities();
            }, "Get Search service capabilities");
            base.DoRequestDelay();
            return response;
        }

        protected DeviceServiceCapabilities GetServiceCapabilities()
        {
            DeviceServiceCapabilities serviceCapabilities = null;
            bool flag = false;
            if (base._credentialsProvider.Security == Security.None)
            {
                base.BeginStep("Get Service Capabilities (no credentials supplied)");
                try
                {
                    serviceCapabilities = base.Client.GetServiceCapabilities();
                }
                catch (AccessDeniedException)
                {
                    base._credentialsProvider.Security = Security.Digest;
                    base.LogStepEvent("DUT requires Digest authentication");
                    base.LogStepEvent("Warning: GetServiceCapabilities shall not require authentication");
                    this._warning = true;
                    flag = true;
                }
                catch (FaultException exception)
                {
                    base.LogFault(exception);
                    if (this.IsAccessDeniedFault(exception))
                    {
                        base._credentialsProvider.Security = Security.WS;
                        base.LogStepEvent("DUT requires WS Username token authentication");
                        base.LogStepEvent("Warning: GetServiceCapabilitiess shall not require authentication");
                        this._warning = true;
                        flag = true;
                    }
                    else
                    {
                        base.LogStepEvent("GetServiceCapabilities failed");
                    }
                }
                catch (Exception exception2)
                {
                    this.RethrowIfStop(exception2);
                    base.LogStepEvent(string.Format("GetServiceCapabilities failed ({0})", exception2.Message));
                }
                base.StepPassed();
                base.DoRequestDelay();
            }
            else
            {
                flag = true;
            }
            if (flag)
            {
                base.BeginStep("Get Service Capabilities");
                try
                {
                    serviceCapabilities = base.Client.GetServiceCapabilities();
                }
                catch (Exception exception3)
                {
                    this.RethrowIfStop(exception3);
                    base.LogStepEvent(string.Format("GetServiceCapabilities failed ({0})", exception3.Message));
                }
                base.StepPassed();
                base.DoRequestDelay();
            }
            return serviceCapabilities;
        }

        protected Service[] GetServices()
        {
            Service[] services = null;
            bool flag = false;
            bool flag2 = false;
            if (base._credentialsProvider.Security == Security.None)
            {
                base.BeginStep("GetServices (no credentials supplied)");
                try
                {
                    services = base.Client.GetServices(false);
                }
                catch (AccessDeniedException)
                {
                    base._credentialsProvider.Security = Security.Digest;
                    base.LogStepEvent("DUT requires Digest authentication");
                    base.LogStepEvent("Warning: GetServices should not require authentication");
                    flag = true;
                }
                catch (FaultException exception)
                {
                    base.LogFault(exception);
                    if (this.IsAccessDeniedFault(exception))
                    {
                        base._credentialsProvider.Security = Security.WS;
                        base.LogStepEvent("DUT requires WS-UsernameToken authentication");
                        base.LogStepEvent("Warning: GetServices should not require authentication");
                        flag = true;
                    }
                    else
                    {
                        base.LogStepEvent(string.Format("GetServices not supported ({0})", exception.Message));
                        flag2 = true;
                    }
                }
                catch (Exception exception2)
                {
                    this.RethrowIfStop(exception2);
                    base.LogStepEvent(string.Format("GetServices not supported ({0})", exception2.Message));
                    flag2 = true;
                }
                base.StepPassed();
                base.DoRequestDelay();
                if (flag2)
                {
                    return null;
                }
            }
            else
            {
                flag = true;
            }
            if (flag)
            {
                base.BeginStep("Get services");
                try
                {
                    services = base.Client.GetServices(false);
                }
                catch (Exception exception3)
                {
                    if (exception3 is FaultException)
                    {
                        base.LogFault(exception3 as FaultException);
                    }
                    this.RethrowIfStop(exception3);
                    base.LogStepEvent(string.Format("GetServices not supported ({0})", exception3.Message));
                }
                base.StepPassed();
                base.DoRequestDelay();
            }
            return services;
        }

        protected MediaUri GetSnapshotUri(string profileToken)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            MediaUri response = null;
            base.RunStep(delegate {
                response = client.GetSnapshotUri(profileToken);
            }, "Get snapshot URI");
            base.DoRequestDelay();
            return response;
        }

        protected VideoEncoderConfigurationOptions GetVideoEncoderConfigurationOptions()
        {
            TestTool.Proxies.Onvif.MediaClient mediaClient = this.MediaClient;
            VideoEncoderConfigurationOptions options = null;
            base.RunStep(delegate {
                options = mediaClient.GetVideoEncoderConfigurationOptions(null, null);
            }, "Get Video Encoder Configuration Options");
            base.DoRequestDelay();
            return options;
        }

        protected VideoEncoderConfiguration[] GetVideoEncoderConfigurations()
        {
            TestTool.Proxies.Onvif.MediaClient mediaClient = this.MediaClient;
            VideoEncoderConfiguration[] configurations = null;
            base.RunStep(delegate {
                configurations = mediaClient.GetVideoEncoderConfigurations();
            }, "Get Video Encoder Configurations");
            base.DoRequestDelay();
            if (configurations != null)
            {
                base.LogTestEvent(string.Format("{0} configurations found", configurations.Length) + Environment.NewLine);
            }
            return configurations;
        }

        protected VideoSourceConfiguration[] GetVideoSourceConfigurations()
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            VideoSourceConfiguration[] configurations = null;
            base.RunStep(delegate {
                configurations = client.GetVideoSourceConfigurations();
            }, "Get Video Source Configurations");
            base.DoRequestDelay();
            if (configurations != null)
            {
                base.LogStepEvent(string.Format("{0} configurations found", configurations.Length) + Environment.NewLine);
            }
            return configurations;
        }

        protected VideoSource[] GetVideoSources()
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            VideoSource[] sources = null;
            base.RunStep(delegate {
                sources = client.GetVideoSources();
            }, "Get Video Sources");
            base.DoRequestDelay();
            if (sources != null)
            {
                base.LogStepEvent(string.Format("{0} sources found", sources.Length) + Environment.NewLine);
            }
            return sources;
        }

        private void HandleException(Exception exc)
        {
            this.RethrowIfStop(exc);
            if (base.InStep)
            {
                base.StepFailed(exc);
            }
            this._warning = true;
        }

        private bool IsAccessDeniedFault(FaultException ex)
        {
            if (!ex.IsValidOnvifFault("Sender/NotAuthorized"))
            {
                return ex.IsValidOnvifFault("Sender/NotAuthorized/SenderNotAuthorized");
            }
            return true;
        }

        private void LogAndNotify(Feature feature, string name, bool supported)
        {
            base.LogStepEvent(string.Format("{0}: {1}", name, supported ? "SUPPORTED" : "NOT SUPPORTED"));
            this.FeatureChecked(feature, supported);
        }

        private void LogAssumeSupported(string name)
        {
            base.LogStepEvent(string.Format("{0} undefined, assume SUPPORTED", name));
        }

        private void LogUsage(string entry)
        {
            base.LogStepEvent(entry);
        }

        protected void RemovePtzConfiguration(string profileToken)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            base.RunStep(() => client.RemovePTZConfiguration(profileToken), "Remove PTZ configuration");
            base.DoRequestDelay();
        }

        protected void RemoveVideoEncoderConfiguration(string profileToken)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            base.RunStep(() => client.RemoveVideoEncoderConfiguration(profileToken), "Remove Video Encoder configuration");
            base.DoRequestDelay();
        }

        protected void RemoveVideoSourceConfiguration(string profileToken)
        {
            TestTool.Proxies.Onvif.MediaClient client = this.MediaClient;
            base.RunStep(() => client.RemoveVideoSourceConfiguration(profileToken), "Remove Video Source configuration");
            base.DoRequestDelay();
        }

        private void ReportFeatureDefined(Feature feature, bool supported)
        {
            if (this.FeatureDefined != null)
            {
                this.FeatureDefined(feature, supported);
            }
        }

        private void ReportUndefined(Feature feature)
        {
            if (this.FeatureDefinitionFailed != null)
            {
                this.FeatureDefinitionFailed(feature);
            }
        }

        private void RethrowIfStop(Exception exc)
        {
            if (exc is StopEventException)
            {
                throw exc;
            }
            if (exc is SocketException)
            {
                throw exc;
            }
        }

        public void RunFeatureDefinition()
        {
            base.RunTest(delegate {
                this._features = new List<Feature>();
                Capabilities capabilities = null;
                capabilities = this.GetCapabilities(null);
                Service[] services = this.GetServices();
                this.FeatureChecked(Feature.GetServices, services != null);
                base.BeginStep("Check GetCapabiilities and GetServices");
                this.LogAndNotify(Feature.GetCapabilities, "GetCapabilities", capabilities != null);
                bool flag = services != null;
                if (flag)
                {
                    base.LogStepEvent("GetServices: SUPPORTED");
                    this.LogUsage("Use GetServices and GetServiceCapabilities for defining features");
                }
                else
                {
                    base.LogStepEvent("GetServices: NOT SUPPORTED");
                }
                if ((capabilities == null) && (services == null))
                {
                    foreach (FeatureNode node in this._featuresSet.Nodes)
                    {
                        if (node.Feature == Feature.DeviceService)
                        {
                            this.SetUndefined(this._featuresSet.FindNode(Feature.Network));
                            this.SetUndefined(this._featuresSet.FindNode(Feature.System));
                            this.SetUndefined(this._featuresSet.FindNode(Feature.DeviceIO));
                        }
                        else
                        {
                            this.SetUndefined(node);
                        }
                    }
                    base.LogStepEvent("GetCapabilities not supported - unable to define other features.");
                    base.LogStepEvent("Neither GetCapabilities, nor GetServices is supported");
                }
                base.StepPassed();
                DeviceServiceCapabilities serviceCapabilities = null;
                if (flag)
                {
                    serviceCapabilities = this.GetServiceCapabilities();
                }
                if ((capabilities != null) || (serviceCapabilities != null))
                {
                    this.DefineDeviceFeatures(capabilities, serviceCapabilities);
                    base.LogStepEvent("Events service is MANDATORY");
                    this.FeatureChecked(Feature.EventsService, true);
                    base.LogTestEvent(string.Empty);
                    this.DefineMediaFeatures(capabilities, services);
                    if (this._mediaSupported)
                    {
                        MediaServiceCapabilities mediaCapabilities = null;
                        if (flag)
                        {
                            mediaCapabilities = this.GetMediaCapabilities();
                        }
                        if ((capabilities != null) || (mediaCapabilities != null))
                        {
                            this.DefineStreamingCapabilities(capabilities, mediaCapabilities);
                        }
                        else
                        {
                            this.LogAssumeSupported("Streaming features");
                            this.SetUndefined(this._featuresSet.FindNode(Feature.RTPRTSPTCP));
                            this.SetUndefined(this._featuresSet.FindNode(Feature.RTPMulticastUDP));
                            this.SetUndefined(this._featuresSet.FindNode(Feature.SnapshotUri));
                        }
                        this.DefineAudioOutputFeatures();
                    }
                    this.DefineIoCapabilities(capabilities, services);
                    this.DefinePtzFeatures(capabilities, services);
                    this.DefineImagingFeatures(capabilities, services);
                    this.DefineAnalyticsFeatures(capabilities, services);
                    this.DefineRecordingCapabilities(capabilities, services);
                    this.DefineSearchCapabilities(capabilities, services);
                    this.DefineReplayCapabilities(capabilities, services);
                    this.DefineReceiverCapabilities(capabilities, services);
                }
                this.DefineDeviceScopes();
                DeviceInformation deviceInformation = this.GetDeviceInformation();
                if (this.DeviceInformationReceived != null)
                {
                    deviceInformation.Capabilities = capabilities;
                    deviceInformation.Services = services;
                    this.DeviceInformationReceived(deviceInformation);
                }
                if (this.Warning)
                {
                    base.LogTestEvent("Some error occurred during feature definition process. ");
                }
            }, () => this.CloseClients());
        }

        protected void SetHomePostion(string profile)
        {
            PTZClient client = this.PtzClient;
            base.RunStep(() => client.SetHomePosition(profile), "Set Home position");
            base.DoRequestDelay();
        }

        protected void SetRelayOutputSettings(string token, RelayOutputSettings settings)
        {
            base.RunStep(() => this.Client.SetRelayOutputSettings(token, settings), string.Format("Set Relay Output settings (IdleState={1}, Mode={0})", settings.IdleState, settings.Mode));
            base.DoRequestDelay();
        }

        private void SetUndefined(FeatureNode node)
        {
            if (node.Status != FeatureStatus.Group)
            {
                this.ReportUndefined(node.Feature);
            }
            this.TransmitUndefined(node.Feature);
        }

        private void StopPTZPositionSearch(string token)
        {
            SearchPortClient client = this.SearchClient;
            base.RunStep(() => client.EndSearch(token), "EndSearch");
            base.DoRequestDelay();
        }

        private void TransmitUndefined(Feature feature)
        {
            FeatureNode node = this._featuresSet.FindNode(feature);
            if (node != null)
            {
                this.TransmitUndefined(node);
            }
        }

        private void TransmitUndefined(FeatureNode node)
        {
            foreach (FeatureNode node2 in node.Nodes)
            {
                if (node2.Status != FeatureStatus.Group)
                {
                    this.ReportUndefined(node2.Feature);
                }
                this.TransmitUndefined(node2);
            }
        }

        private void TransmitUnsupported(Feature feature)
        {
            FeatureNode node = this._featuresSet.FindNode(feature);
            if (node != null)
            {
                this.TransmitUnsupported(node);
            }
        }

        private void TransmitUnsupported(FeatureNode node)
        {
            foreach (FeatureNode node2 in node.Nodes)
            {
                if (node2.Status != FeatureStatus.Group)
                {
                    this.ReportFeatureDefined(node2.Feature, false);
                }
                this.TransmitUnsupported(node2);
            }
        }

        protected ImagingPortClient ImagingClient
        {
            get
            {
                if ((this._imagingClient == null) && this._imagingSupported)
                {
                    Binding binding = base.CreateBinding(false);
                    this._imagingClient = new ImagingPortClient(binding, new EndpointAddress(this._imagingServiceAddress));
                    base.AttachSecurity(this._imagingClient.Endpoint);
                    base.SetupChannel(this._imagingClient.InnerChannel);
                }
                return this._imagingClient;
            }
        }

        protected DeviceIOPortClient IoClient
        {
            get
            {
                if ((this._ioClient == null) && this._ioSupported)
                {
                    Binding binding = base.CreateBinding(false);
                    this._ioClient = new DeviceIOPortClient(binding, new EndpointAddress(this._ioServiceAddress));
                    base.AttachSecurity(this._ioClient.Endpoint);
                    base.SetupChannel(this._ioClient.InnerChannel);
                }
                return this._ioClient;
            }
        }

        protected TestTool.Proxies.Onvif.MediaClient MediaClient
        {
            get
            {
                if ((this._mediaClient == null) && this._mediaSupported)
                {
                    Binding binding = base.CreateBinding(false);
                    this._mediaClient = new TestTool.Proxies.Onvif.MediaClient(binding, new EndpointAddress(this._mediaServiceAddress));
                    base.AttachSecurity(this._mediaClient.Endpoint);
                    base.SetupChannel(this._mediaClient.InnerChannel);
                }
                return this._mediaClient;
            }
        }

        protected PTZClient PtzClient
        {
            get
            {
                if ((this._ptzClient == null) && this._ptzSupported)
                {
                    Binding binding = base.CreateBinding(false);
                    this._ptzClient = new PTZClient(binding, new EndpointAddress(this._ptzServiceAddress));
                    base.AttachSecurity(this._ptzClient.Endpoint);
                    base.SetupChannel(this._ptzClient.InnerChannel);
                }
                return this._ptzClient;
            }
        }

        protected ReceiverPortClient ReceiverClient
        {
            get
            {
                if ((this._receiverClient == null) && this._receiverSupported)
                {
                    Binding binding = base.CreateBinding(false);
                    this._receiverClient = new ReceiverPortClient(binding, new EndpointAddress(this._receiverServiceAddress));
                    base.AttachSecurity(this._receiverClient.Endpoint);
                    base.SetupChannel(this._receiverClient.InnerChannel);
                }
                return this._receiverClient;
            }
        }

        protected RecordingPortClient RecordingClient
        {
            get
            {
                if ((this._recordingControlClient == null) && this._recordingControlSupported)
                {
                    Binding binding = base.CreateBinding(false);
                    this._recordingControlClient = new RecordingPortClient(binding, new EndpointAddress(this._recordingControlServiceAddress));
                    base.AttachSecurity(this._recordingControlClient.Endpoint);
                    base.SetupChannel(this._recordingControlClient.InnerChannel);
                }
                return this._recordingControlClient;
            }
        }

        protected ReplayPortClient ReplayClient
        {
            get
            {
                if ((this._replayClient == null) && this._replaySupported)
                {
                    Binding binding = base.CreateBinding(false);
                    this._replayClient = new ReplayPortClient(binding, new EndpointAddress(this._replayServiceAddress));
                    base.AttachSecurity(this._replayClient.Endpoint);
                    base.SetupChannel(this._replayClient.InnerChannel);
                }
                return this._replayClient;
            }
        }

        protected SearchPortClient SearchClient
        {
            get
            {
                if ((this._searchClient == null) && this._searchSupported)
                {
                    Binding binding = base.CreateBinding(false);
                    this._searchClient = new SearchPortClient(binding, new EndpointAddress(this._searchServiceAddress));
                    base.AttachSecurity(this._searchClient.Endpoint);
                    base.SetupChannel(this._searchClient.InnerChannel);
                }
                return this._searchClient;
            }
        }

        public static TestInfo This
        {
            get
            {
                if (_descriptor == null)
                {
                    _descriptor = new TestInfo();
                    _descriptor.Name = "DEFINE FEATURES";
                    _descriptor.Method = typeof(FeaturesDefinitionProcess).GetMethod("RunFeatureDefinition");
                    _descriptor.ProcessType = ProcessType.FeatureDefinition;
                }
                return _descriptor;
            }
        }

        public bool Warning
        {
            get
            {
                return this._warning;
            }
        }
    }
}

